import binascii
import logging
import serial

class IT6720SerialController:
    def __init__(self, port='COM1', baudrate=4800, timeout=1):
        """
        初始化 IT6720 串口控制器。

        :param port: 串口号,例如 'COM3' 或 '/dev/ttyUSB0'
        :param baudrate: 波特率,默认为 9600
        :param timeout: 超时时间,默认为 1 秒
        """
        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout)
        # # 发送初始命令
        # initial_command = 'AA 01 20 01 01 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
        # command_bytes = self.str_to_hex_bytes(initial_command)
        # reqstr = binascii.b2a_hex(bytearray(command_bytes), ' ')
        # print("reqstr: " + str(reqstr))
        # self.ser.write(bytes(command_bytes))
        # # 读取设备的响应
        # response = self.ser.readline()
        # if response[2] == 0x12 and response[3] == 0x80:
        #     print("connect power success")
        # else:
        #     print("connect power failed")
        # resqstr = binascii.b2a_hex(bytearray(response), ' ')
        # print("response: " + str(resqstr))

    @staticmethod
    def str_to_hex_bytes(hex_string):
        """
        转换字符串为数组,并添加 CRC 校验。

        :param hex_string: 输入的十六进制字符串
        :return: 包含 CRC 校验的字节数组
        """
        hex_string = str(hex_string).replace(' ', '').replace('[', '').replace(']', '').replace('\'', '')

        if ((len(hex_string) % 2) != 0):
            hex_string += " "

        c_16_temp = list(hex_string)
        ilen = int(len(c_16_temp) / 2)
        hexBytes = [0] * ilen
        for index in range(ilen):
            hexBytes[index] = int((c_16_temp[2 * index] + c_16_temp[2 * index + 1]),16)
        crc = sum(hexBytes) & 0xFF
        hexBytes.append(crc)
        return hexBytes
    
    def send_command(self, command):
        """
        向 IT6720 发送命令。

        :param command: 要发送的命令,可以是字符串或 16 进制字节数组
        :return: 设备返回的响应
        """

        # 判断传入变量类型
        if isinstance(command, str):
            req = self.str_to_hex_bytes(command)
        else:
            req = command

        reqstr = binascii.b2a_hex(bytearray(req), ' ')
        print("reqstr: " + str(reqstr))
        
        # 检查串口是否可用
        if not self.ser.is_open:
            print("Serial port is not open, skipping command send.")
            return None
            
        self.ser.write(req)
        # 读取设备的响应
        response = self.ser.readline()
        resqstr = binascii.b2a_hex(bytearray(response), ' ')
        print("response: " + str(resqstr))

        return response
    
    def connect(self):
        """
        连接到 IT6720 电源。
        """
        response = self.send_command('AA 01 20 01 01 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00')
        if response[2] == 0x12 and response[3] == 0x80:
            print("connect power success")
            return True
        else:
            print("connect power failed")
            return False

    def turn_on_power(self):
        """
        打开 IT6720 电源输出。
        """
        commandStr = 'AA 01 21 01 01 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
        response = self.send_command(commandStr)

    def turn_off_power(self):
        """
        关闭 IT6720 电源输出。
        """
        commandStr = 'AA 01 21 00 01 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
        response = self.send_command(commandStr)

    def set_voltage(self, voltage):
        """
        设置 IT6720 的输出电压。

        :param voltage: 要设置的电压值,单位为伏特
        第四节 设定电压值低字的低字节
        第五节 设定电压值低字的高字节
        第六节 设定电压值高字的低字节
        第七节 设定电压值高字的高字节
        """
         # 将电压值转换为整数,假设电压值以 100 倍的形式存储
        voltage_int = int(voltage * 1000)
        # 拆分电压值为不同字节
        low_low = voltage_int & 0xFF
        low_high = (voltage_int >> 8) & 0xFF
        high_low = (voltage_int >> 16) & 0xFF
        high_high = (voltage_int >> 24) & 0xFF

        # 构建命令字符串
        command_template = 'AA 01 23 {:02X} {:02X} {:02X} {:02X} 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
        commandStr = command_template.format(low_low, low_high, high_low, high_high)
        response = self.send_command(commandStr)
        logging.info(f'Set voltage to {voltage} V')

    def set_current(self, current):
        """
        设置 IT6720 的输出电流。

        :param current: 要设置的电流值,单位为安培
        """
        self.send_command(f'CURR {current}')

    def get_voltage(self):
        """
        获取 IT6720 的当前输出电压。

        :return: 当前输出电压值,单位为伏特
        """
        response = self.send_command('MEAS:VOLT?')
        return float(response)

    def get_current(self):
        """
        获取 IT6720 的当前输出电流。

        :return: 当前输出电流值,单位为安培
        """
        response = self.send_command('MEAS:CURR?')
        return float(response)

    def close(self):
        """
        关闭串口连接。
        """
        self.send_command(self.str_to_hex_bytes('AA 01 20 00 01 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'))
        self.ser.close()

# 示例：创建 IT6720SerialController 实例并使用
if __name__ == "__main__":

        # 请替换为实际的串口号
        serial_port = 'COM1'
        # 创建 IT6720SerialController 实例
        controller = IT6720SerialController(serial_port)
        controller.connect()
    #     # 打开电源输出
    #     controller.turn_on()
        # 设置输出电压为 5V
        controller.set_voltage(5)
    #     # 设置输出电流为 1A
    #     controller.set_current(1)
    #     # 获取当前输出电压
    #     voltage = controller.get_voltage()
    #     print(f'当前电压: {voltage} V')
    #     # 获取当前输出电流
    #     current = controller.get_current()
    #     print(f'当前电流: {current} A')
    #     # 关闭电源输出
    #     controller.turn_off()
        # 关闭串口连接
        controller.close()